package com.liveinstars.im.core;

import com.liveinstars.im.core.service.ChatServerService;
import com.liveinstars.im.entity.Msg;
import com.liveinstars.im.handler.*;
import com.onepiece.cache.service.CacheService;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

@Service
@Scope("singleton")
public class NettyServerBootstrap {
	@Autowired
	private ClientLoginHandler clientLoginHandler;

	@Autowired
	private ServerLoginHandler serverLoginHandler;

	@Autowired
	private PingHandler pingHandler;

	@Autowired
	private ChatHandler chatHandler;

	@Autowired
	private MsgChatHandler msgChatHandler;

	@Autowired
	private ClientRequesHandler clientRequesHandler;

	@Autowired
	private ServerClientBootstrap serverClientBootstrap;

	@Autowired
	private NettyServerBootstrap nettyServerBootstrap;

	private static final Logger LOGGER = LoggerFactory.getLogger(NettyServerBootstrap.class);
	/**
	 * 本机内网ip
	 */
	@Value("${netty.server.ip}")
	private String ip;

	/**
	 * 本机外网ip
	 */
	@Value("${netty.server.outip}")
	private String outIp;
	/**
	 * 本机服务端监听端口
	 */
	@Value("${netty.server.port}")
	private int port;

	/**
	 * 本机服务端监听端口
	 */
	@Value("${netty.server.name}")
	private String name;

	@Autowired
	private ChatServerService chatServerService;

	private EventLoopGroup boss;

	private EventLoopGroup worker;

	@Autowired
	CacheService cache;


	@PostConstruct
	public void bind() throws InterruptedException {
		boss = new NioEventLoopGroup();
		worker = new NioEventLoopGroup();
		ServerBootstrap bootstrap = new ServerBootstrap();
		bootstrap.group(boss, worker);
		bootstrap.channel(NioServerSocketChannel.class);
		bootstrap.option(ChannelOption.SO_BACKLOG, 128);
		// 通过NoDelay禁用Nagle,使消息立即发出去，不用等待到一定的数据量才发出去
		bootstrap.option(ChannelOption.TCP_NODELAY, true);

		// 保持长连接状态
		bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
		bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
			@Override
			protected void initChannel(SocketChannel socketChannel)
					throws Exception {
				ChannelPipeline p = socketChannel.pipeline();
				//websocket协议支持
				p.addLast(new IdleStateHandler(0, 0, 55));
				p.addLast(new ProtobufVarint32FrameDecoder());
				p.addLast(new ProtobufDecoder(Msg.Message.getDefaultInstance()));
				p.addLast(new ProtobufVarint32LengthFieldPrepender());
				p.addLast(new ProtobufEncoder());

				p.addLast(msgChatHandler);
				p.addLast(clientLoginHandler);
				p.addLast(serverLoginHandler);
				p.addLast(pingHandler);
				p.addLast(chatHandler);
				p.addLast(clientRequesHandler);
			}
		});
		ChannelFuture f = bootstrap.bind(port).sync();
		if (f.isSuccess()) {
			chatServerService.register();
			serverClientBootstrap.start();
		}
		Runtime.getRuntime().addShutdownHook(new Thread(){
			@Override
			public void run() {
				nettyServerBootstrap.shutdown();
			}
		});
	}

	public void shutdown() {
		chatServerService.offline();
		serverClientBootstrap.shutdown();
		worker.shutdownGracefully();
		boss.shutdownGracefully();
	}



}